package com.changzhi.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changzhi.common.constans.Constants;
import com.changzhi.common.constans.RedisConstans;
import com.changzhi.common.enums.InvitePrizeEnum;
import com.changzhi.common.enums.InvitePrizeSourceEnum;
import com.changzhi.common.exception.ServiceException;
import com.changzhi.common.util.BaseUtil;
import com.changzhi.common.util.DateUtil;
import com.changzhi.ldyl.model.*;
import com.changzhi.ldyl.model.dto.InviteDto;
import com.changzhi.ldyl.model.vo.InviteVo;
import com.changzhi.ldyl.model.vo.NewLotteryVo;
import com.changzhi.ldyl.model.vo.PrizeVo;
import com.changzhi.ldyl.model.vo.UserVo;
import com.changzhi.mapper.*;
import com.changzhi.service.GiftService;
import com.changzhi.service.InviteService;
import com.changzhi.service.UserService;
import com.changzhi.util.CommonUtil;
import com.changzhi.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:
 * @author: 小落
 * @date: 2020年11月04日
 */
@Slf4j
@Service
public class InviteServiceImpl extends ServiceImpl<InviteMapper, Invite> implements InviteService {

	@Resource
	private InviteExchangeMapper inviteExchangeMapper;
	@Resource
	private	InviteLinkRecordMapper inviteLinkRecordMapper;
	@Resource
	private InviteMapper inviteMapper;
	@Resource
	private	InvitePrizeMapper invitePrizeMapper;
	@Resource
	private InviteRecordMapper inviteRecordMapper;
	@Resource
	private	InviteWalletMapper inviteWalletMapper;
	@Resource
	private UserWalletMapper userWalletMapper;
	@Resource
	private UserAccountBookMapper userAccountBookMapper;
	@Resource
	private InviteRateMapper inviteRateMapper;
	@Resource
	private InviteCoinLogMapper inviteCoinLogMapper;
	@Autowired
	private GiftService giftService;
	@Resource
	private OrderDayMapper orderDayMapper;
	@Resource
	private RedisUtil redisUtil;
	@Value("${spring.profiles.active}")
	private String env;
	@Resource
	private ExternalUserBindingMapper externalUserBindingMapper;
	@Resource
	private UserService userService;
	@Resource
	private UserVerifyMapper userVerifyMapper;
	@Resource
	private UserDeviceInfoMapper userDeviceInfoMapper;
	@Resource
	private InviteAwardMapper inviteAwardMapper;
	@Resource
	private ChatChannelUserMapper chatChannelUserMapper;
	//邀请期数
	public final static Integer INVITE_ID = 1;
	public final static Map<String, LocalDateTime> TIME_MAP = new HashMap<>();


	@PostConstruct
	public void init(){
		redisUtil.del(RedisConstans.INVITE + INVITE_ID);
		Invite invite = getInvite(INVITE_ID);
		//存活动时间
		TIME_MAP.put("startTime", invite.getStartTime());
		TIME_MAP.put("endTime", invite.getEndTime());
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public void doMqDataByHandler(InviteDto param) {
		//userId, mobile, ip, deviceInfo
		//1.是否在活动时间内
		if(!DateUtil.isBetweenTime(TIME_MAP.get("startTime"), TIME_MAP.get("endTime")) && "prod".equals(env)){
			//测试账号通行
			if(!CommonUtil.getTestMobileList().contains(param.getMobile())){
				return;
			}
		}
		if(StringUtils.isBlank(param.getDeviceInfo())){
			log.warn("methodName:doMqDataByHandler,设备信息不能为空,inviteDto={}", JSON.toJSONString(param));
			return;
		}
		//判断是否为模拟器
		if("3".equals(param.getDeviceType())){
			log.warn("methodName:doMqDataByHandler,模拟器用户,inviteDto={}", JSON.toJSONString(param));
			return;
		}
		//判断手机号是否为空
		if(StringUtils.isBlank(param.getMobile())){
			log.warn("methodName:doMqDataByHandler,手机号为空,inviteDto={}", JSON.toJSONString(param));
			return;
		}
		//判断手机号是否为虚拟号
		if(BaseUtil.isVirtualMobile(param.getMobile())){
			log.warn("methodName:doMqDataByHandler,虚拟手机号,inviteDto={}", JSON.toJSONString(param));
			return;
		}
		//判断用户id是否存在
		LambdaQueryWrapper<InviteRecord> wrapper1 = new LambdaQueryWrapper<>();
		wrapper1.eq(InviteRecord::getUserId, param.getUserId()).last("limit 1");
		InviteRecord record1 = inviteRecordMapper.selectOne(wrapper1);
		if (record1 != null) {
			log.warn("methodName:doMqDataByHandler,用户id已存在,inviteDto={}", JSON.toJSONString(param));
			return ;
		}
		//判断手机号是否存在
		LambdaQueryWrapper<InviteRecord> wrapper2 = new LambdaQueryWrapper<>();
		wrapper2.eq(InviteRecord::getMobile, param.getMobile()).last("limit 1");
		InviteRecord record2 = inviteRecordMapper.selectOne(wrapper2);
		if (record2 != null) {
			log.warn("methodName:doMqDataByHandler,手机号已存在,inviteDto={}", JSON.toJSONString(param));
			return ;
		}
		//判断手机号是否存在2
		LambdaQueryWrapper<UserVerify> verifyWrapper = new LambdaQueryWrapper<>();
		verifyWrapper.eq(UserVerify::getMobile, param.getMobile()).lt(UserVerify::getCreateTime, LocalDateTime.now().minusMinutes(1)).last("limit 1");
		UserVerify verify = userVerifyMapper.selectOne(verifyWrapper);
		if (verify != null) {
			log.warn("methodName:doMqDataByHandler,手机号已存在2,inviteDto={}", JSON.toJSONString(param));
			return ;
		}
		//判断设备信息是否存在
		LambdaQueryWrapper<InviteRecord> wrapper3 = new LambdaQueryWrapper<>();
		wrapper3.eq(InviteRecord::getDeviceInfo, param.getDeviceInfo()).last("limit 1");
		InviteRecord record3 = inviteRecordMapper.selectOne(wrapper3);
		if (record3 != null) {
			log.warn("methodName:doMqDataByHandler,手设备信息已存在,inviteDto={}", JSON.toJSONString(param));
			return ;
		}
		//判断设备信息是否存在2
		LambdaQueryWrapper<UserDeviceInfo> deviceWrapper = new LambdaQueryWrapper<>();
		String[] split = param.getDeviceInfo().split("_");
		if(split.length > 0 && !"null".equals(split[0])){
			deviceWrapper.eq(UserDeviceInfo::getAndroidId, split[0]);
		}
		if(split.length > 1 && !"null".equals(split[1])){
			deviceWrapper.eq(UserDeviceInfo::getDeviceId, split[1]);
		}
		if(split.length > 2 && !"null".equals(split[2])){
			deviceWrapper.eq(UserDeviceInfo::getOaid, split[2]);
		}
		deviceWrapper.lt(UserDeviceInfo::getCreateTime, LocalDateTime.now().minusMinutes(1)).last("limit 1");
		UserDeviceInfo deviceInfo = userDeviceInfoMapper.selectOne(deviceWrapper);
		if (deviceInfo != null) {
			log.warn("methodName:doMqDataByHandler,手设备信息已存在2,inviteDto={}", JSON.toJSONString(param));
			return ;
		}
		//查询邀请人钱包
		LambdaQueryWrapper<InviteWallet> wrapper4 = new LambdaQueryWrapper<>();
		wrapper4.eq(InviteWallet::getInvitteCode, param.getInviteCode()).last("limit 1");
		InviteWallet inviteWallet = inviteWalletMapper.selectOne(wrapper4);
		if (inviteWallet == null) {
			log.warn("methodName:doMqDataByHandler,钱包不存在,inviteDto={}", JSON.toJSONString(param));
			return ;
		}
		//是否有权限（奶爸没有权限）
		if(!isAuth(inviteWallet.getUserId())){
			log.warn("methodName:doMqDataByHandler,没有参与权限,inviteDto={}", JSON.toJSONString(param));
			return ;
		}
		//判断是否超过每日邀请数量
		Invite invite = getInvite(INVITE_ID);
		Integer limit = isDayLimit(inviteWallet.getUserId(), invite.getProperty2());
		if(limit == 1){
			log.warn("methodName:doMqDataByHandler,邀请用户已超过上限, limit ={} userId={},inviteDto={}", limit, inviteWallet.getUserId(), JSON.toJSONString(param));
			return;
		}
		//插入邀请记录
		InviteRecord record = new InviteRecord();
		record.setInviteCode(inviteWallet.getInvitteCode());
		record.setInviteId(INVITE_ID);
		record.setTargetId(inviteWallet.getUserId());
		record.setUserId(param.getUserId());
		record.setDeviceInfo(param.getDeviceInfo());
		record.setMobile(param.getMobile());
		record.setCreateDate(LocalDate.now());
		inviteRecordMapper.insert(record);
		//给新用户发放新人奖励
		newcomerReward(param.getUserId());
		//累计邀请奖励
		cumulativeInvitationReward(inviteWallet.getUserId());
		//暂存表
		InviteAward award = new InviteAward();
		award.setInviteRecordId(record.getId());
		award.setUserId(record.getUserId());
		award.setTargetId(record.getTargetId());
		award.setType(0);
		award.setStatus(0);
		inviteAwardMapper.insert(award);
	}

	@Override
	public void inviteGivePrize() {
		LambdaQueryWrapper<InviteAward> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(InviteAward::getStatus, 0);
		List<InviteAward> awardList = inviteAwardMapper.selectList(wrapper);
		for (InviteAward award : awardList) {
			//条件1.是否进过房间
			LambdaQueryWrapper<ChatChannelUser> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.eq(ChatChannelUser::getUserId, award.getUserId()).ne(ChatChannelUser::getPowerType, "OWNER");
			Integer count = chatChannelUserMapper.selectCount(queryWrapper);
			if(count == null || count == 0){
				continue;
			}
			//修改状态
			int row = inviteMapper.updateByAwardStatus(award.getId());
			if(row > 0){
				//给邀请人增加友情币
				Integer num = lottery();
				addCoin(null, award.getUserId(), award.getTargetId(), num, 0, 0);
				log.warn("methodName:inviteGivePrize，奖励发放成功，award={}",JSON.toJSONString(award));
			}
		}
	}

	//累计邀请奖励
	private void cumulativeInvitationReward(String targetId){
		List<InvitePrize> prizeList = getInvitePrizeList(InvitePrizeEnum.ACCUMULATE_AWARD.getType());
		List<InvitePrize> filterList = prizeList.stream().filter(p -> p.getSource() == InvitePrizeSourceEnum.DECORATE.getValue()).collect(Collectors.toList());
		if(CollectionUtils.isEmpty(filterList)){
			log.error("methodName:cumulativeInvitationReward, targetId={}", targetId);
			return;
		}
		Integer count = inviteRecordMapper.selectCount(new LambdaQueryWrapper<InviteRecord>().eq(InviteRecord::getInviteId, INVITE_ID).eq(InviteRecord::getTargetId , targetId));
		for (InvitePrize prize : filterList) {
			if(count >= prize.getExNum()){
				String key = RedisConstans.putRediskey(RedisConstans.INVITE_CUMULATIE_DECORATE, INVITE_ID, prize.getExNum(),targetId);
				//查询奖励是否已发放
				if(redisUtil.get(key) != null){
					continue;
				}
				LambdaQueryWrapper<InviteExchange> exWrapper = new LambdaQueryWrapper<>();
				exWrapper.eq(InviteExchange::getInviteId, INVITE_ID).eq(InviteExchange::getUserId, targetId).eq(InviteExchange::getType, prize.getType()).eq(InviteExchange::getSource, prize.getSource()).eq(InviteExchange::getGiftId, prize.getGiftId());
				Integer row = inviteExchangeMapper.selectCount(exWrapper);
				if(row > 0){
					continue;
				}
				//发放奖励
				givePrize(targetId, prize);
				redisUtil.set(key, "1", RedisConstans.ONE_YEAR);
			}
		}
	}

	@Override
	public void doInviteByOrderSuccess(String userId) {
		log.info("methodName:doInviteByOrderSuccess, userId={}", userId);
		//1.是否在活动时间内
		if(!DateUtil.isBetweenTime(TIME_MAP.get("startTime"), TIME_MAP.get("endTime")) && "prod".equals(env)){
			return;
		}
		//2.查询邀请记录是否存在
		LambdaQueryWrapper<InviteRecord> wrapper =  new LambdaQueryWrapper<>();
		wrapper.eq(InviteRecord::getInviteId, INVITE_ID).eq(InviteRecord::getUserId, userId).last("limit 1");
		InviteRecord record = inviteRecordMapper.selectOne(wrapper);
		if(record == null){
			log.info("methodName:doInviteByOrderSuccess, userId={},邀请记录不存在", userId);
			return;
		}
		//3.查询奖品
		List<InvitePrize> prizeList = getInvitePrizeList(InvitePrizeEnum.ACCUMULATE_AWARD.getType());
		if(CollectionUtils.isEmpty(prizeList)){
			log.error("methodName:doMqDataByOrderSuccess, 奖品不存在 userId={}", userId);
			return;
		}
		List<InvitePrize> filterList = prizeList.stream().filter(p -> p.getSource().equals(InvitePrizeSourceEnum.COIN.getValue())).collect(Collectors.toList());
		if(CollectionUtils.isEmpty(filterList)){
			log.error("methodName:doMqDataByOrderSuccess, 奖品不存在 userId={}", userId);
			return;
		}
		InvitePrize prize = filterList.get(0);
		Integer everyDiamond = Integer.valueOf(prize.getExNum());
		//查询累计充值金额
		Double sum = orderDayMapper.selectSumPrice(userId, TIME_MAP.get("startTime").toLocalDate(), TIME_MAP.get("endTime").toLocalDate());
		if(sum * 10 < everyDiamond){
			log.info("methodName:doInviteByOrderSuccess,sum={},everyDiamond={},userId={},充值金额不够", sum, everyDiamond, userId);
			return;
		}
		LambdaQueryWrapper<InviteCoinLog> logWrapper = new LambdaQueryWrapper<>();
		logWrapper.eq(InviteCoinLog::getInviteId, INVITE_ID).eq(InviteCoinLog::getUserId, record.getUserId()).eq(InviteCoinLog::getTargetId, record.getTargetId()).eq(InviteCoinLog::getType, 1);
		Integer count = inviteCoinLogMapper.selectCount(logWrapper);
		if(count > 0){
			log.warn("methodName:doMqDataByOrderSuccess, 累计充值已发放 userId={}", userId);
			return;
		}
		//累计增加友情币
		addCoin(null, record.getUserId(), record.getTargetId(), prize.getTotalValue(), 1, 1000);

		/*//查询累计充值金额		（总-总已用）/1000
		//查询是否已增加友情币
		Integer everyDiamond = Integer.valueOf(prize.getExNum());
		LambdaQueryWrapper<InviteCoinLog> logWrapper = new LambdaQueryWrapper<>();
		logWrapper.eq(InviteCoinLog::getInviteId, INVITE_ID).eq(InviteCoinLog::getUserId, record.getUserId()).eq(InviteCoinLog::getTargetId, record.getTargetId()).eq(InviteCoinLog::getType, 1);
		Integer computeDiamond = inviteCoinLogMapper.selectSumComputeDiamond(INVITE_ID, record.getUserId(), record.getTargetId(), 1);
		Double count = (sum * 10 - computeDiamond) / everyDiamond;
		if(count < 1){
			log.info("methodName:doInviteByOrderSuccess, count={},sum={},computeDiamond={},everyDiamond={},computeDiamond={},充值金额不够", count, sum, computeDiamond, computeDiamond);
			return;
		}
		//累计增加友情币
		addCoin(null, record.getUserId(), record.getTargetId(), prize.getTotalValue() * count.intValue(), 1, everyDiamond * count.intValue());*/
	}

	@Override
	public void doMqDataByUserInvite(String msg) {
		UserInvitationAward invitationAward = JSON.parseObject(msg, UserInvitationAward.class);
		String userId = invitationAward.getUserId();
		if(StringUtils.isBlank(userId)){
			return;
		}
		//1.是否在活动时间内
		if(!DateUtil.isBetweenTime(TIME_MAP.get("startTime"), TIME_MAP.get("endTime")) && "prod".equals(env)){
			//测试账号通行
			if(!CommonUtil.getTestAccountList().contains(invitationAward.getInviterUserId())){
				return;
			}
		}
		//2.是否为奶爸邀请
		LambdaQueryWrapper<ExternalUserBinding> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(ExternalUserBinding::getUserId, invitationAward.getInviterUserId()).last("limit 1");
		ExternalUserBinding binding = externalUserBindingMapper.selectOne(wrapper);
		if(binding == null){
			return;
		}
		List<InvitePrize> prizeList = getInvitePrizeList(InvitePrizeEnum.EXTERNAL_NEW_AWARD.getType());
		for (InvitePrize prize : prizeList) {
			//查询奖励是否已发放
			LambdaQueryWrapper<InviteExchange> exWrapper = new LambdaQueryWrapper<>();
			exWrapper.eq(InviteExchange::getInviteId, INVITE_ID).eq(InviteExchange::getUserId, userId).eq(InviteExchange::getType, prize.getType()).eq(InviteExchange::getSource, prize.getSource()).eq(InviteExchange::getGiftId, prize.getGiftId());
			Integer row = inviteExchangeMapper.selectCount(exWrapper);
			if(row > 0){
				continue;
			}
			//3.是否已经获得奖励
			givePrize(userId, prize);
		}
	}

	@Override
	public InviteVo share(String code, String ip) {
		List<InvitePrize> exList = getInvitePrizeList(InvitePrizeEnum.EX_PRIZE.getType());
		List<PrizeVo> exPrizeList = new ArrayList<>();
		for (InvitePrize prize : exList) {
			exPrizeList.add(new PrizeVo(prize.getId(),prize.getName(),prize.getIcon(),prize.getDayNum(),prize.getNum(),prize.getExNum(),prize.getSource()));
		}
		//插入访问记录
		insertVisitRecord(code, ip);
		//返回
		InviteVo result = new InviteVo();
		result.setPrizeList(exPrizeList);
		return result;
	}

	//是否有参与权限
	private boolean isAuth(String userId){
		Boolean auth = redisUtil.get(RedisConstans.INVITE_AUTH + INVITE_ID + userId);
		if(auth != null){
			return auth;
		}
		Integer count = externalUserBindingMapper.selectCount(new LambdaQueryWrapper<ExternalUserBinding>().eq(ExternalUserBinding::getUserId, userId));
		if(count > 0){
			auth = false;
		} else {
			auth = true;
		}
		redisUtil.set(RedisConstans.INVITE_AUTH + INVITE_ID + userId, auth, RedisConstans.TWO_HOUR);
		return auth;
	}

	//是否超出每日限制
	private Integer isDayLimit(String userId, String limitNum){
		Integer limit = 0;
		if(StringUtils.isBlank(userId)){
			return limit;
		}
		LambdaQueryWrapper<InviteRecord> inviteWrapper = new LambdaQueryWrapper<>();
		inviteWrapper.eq(InviteRecord::getInviteId, INVITE_ID).eq(InviteRecord::getTargetId, userId).eq(InviteRecord::getCreateDate, LocalDate.now());
		Integer count = inviteRecordMapper.selectCount(inviteWrapper);
		if(Integer.valueOf(limitNum) <= count){
			limit = 1;
		}
		return limit;
	}

	@Override
	public InviteVo getBaseInfo(InviteDto inviteDto) {
		String userId = inviteDto.getUserId();
		Integer auth = 1;
		Integer coin = 0;
		Integer showEndTip = 0;//活动结束前1天弹窗
		Integer showActivityEnd = 0;//活动结束
		Integer newUserPrizeTip = 0;
		String inviteCode = "";
		User user = new User();
		Invite invite = getInvite(INVITE_ID);
		LocalDateTime now = LocalDateTime.now();
		if(invite.getEndTime().toLocalDate().isEqual(now.toLocalDate())){
			showEndTip = 1;
		}
		if(now.isAfter(invite.getEndTime())){
			showActivityEnd = 1;
		}
		if(StringUtils.isNotBlank(userId)){
			//查用户
			user = userService.getUser(userId);
			//是否有参与活动权限
			if(!isAuth(userId)){
				auth = 0;
			} else {
				//1.钱包表是否有数据，没有则生成
				InviteWallet wallet = getWallet(userId);
				if(wallet == null){
					inviteCode = getInviteCode();
					InviteWallet record = new InviteWallet();
					record.setInviteId(INVITE_ID);
					record.setUserId(userId);
					record.setAmount(0);
					record.setInvitteCode(inviteCode);
					inviteWalletMapper.insert(record);
				} else {
					//活动结束，友情币返回0
					if(invite.getEndTime().isBefore(now)){
						coin = 0;
					} else {
						coin = wallet.getAmount();
					}
					inviteCode = wallet.getInvitteCode();
				}
			}
		}
		//奖品
		List<InvitePrize> exList = getInvitePrizeList(InvitePrizeEnum.EX_PRIZE.getType());
		List<PrizeVo> exPrizeList = new ArrayList<>();
		for (InvitePrize prize : exList) {
			exPrizeList.add(new PrizeVo(prize.getId(),prize.getName(),prize.getIcon(),prize.getDayNum(),prize.getNum(),prize.getExNum(),prize.getSource()));
		}
		String baseUrl = "https://activity.boba.hk";
		if(!"aliyun".equals(env)){
			baseUrl = "https://tactivity.boba.hk";
		}
		//返回
		InviteVo result = new InviteVo();
		result.setCoin(coin)
				.setInviteCode(inviteCode)
				.setInviteUrl(StringUtils.isBlank(inviteCode) ?  "" : baseUrl + inviteCode)
				.setPrizeList(exPrizeList)
				.setEndTimeStr(DateUtil.localDateTimeToString(invite.getEndTime()))
				.setLimit(isDayLimit(userId, invite.getProperty2()))//是否超出每日限制
				.setShowEndTip(showEndTip)
				.setNewUserPrizeTip(newUserPrizeTip)
				.setAuth(auth)
				.setShowActivityEnd(showActivityEnd)
				.setAccountId(user.getAccountId())
				.setNickname(user.getNickname());
		return result;
	}


	//奖品
	private List<InvitePrize> getInvitePrizeList(Integer type){
		List<InvitePrize> prizeList = (List<InvitePrize>) redisUtil.hget(RedisConstans.INVITE_PRIZE + INVITE_ID, type.toString());
		if(CollectionUtils.isEmpty(prizeList)){
			prizeList = invitePrizeMapper.selectList(new LambdaQueryWrapper<InvitePrize>().eq(InvitePrize::getInviteId, INVITE_ID).eq(InvitePrize::getType, type).orderByDesc(InvitePrize::getSort));
			redisUtil.hset(RedisConstans.INVITE_PRIZE + INVITE_ID, type.toString(), prizeList, RedisConstans.TWO_HOUR);
		}
		return prizeList;
	}

	@Override
	public InviteVo getOtherInfo(InviteDto inviteDto) {
		String userId = inviteDto.getUserId();
		Integer newUserPrizeTip = 0;
		Invite invite = getInvite(INVITE_ID);
		LocalDateTime now = LocalDateTime.now();
		InviteVo result = new InviteVo();
		/*if(invite.getEndTime().isBefore(now)){
			return new InviteVo();
		}*/
		//最新10条奖励
		List<PrizeVo> prizeList = inviteExchangeMapper.selectLastList(INVITE_ID);
		/*//新人礼包
		InviteRecord record = inviteRecordMapper.selectOne(new LambdaQueryWrapper<InviteRecord>().eq(InviteRecord::getInviteId, INVITE_ID).eq(InviteRecord::getUserId, userId));
		if(record != null && record.getTip() == 1){
			newUserPrizeTip = 1;
			//更新为已提示
			InviteRecord recordDb = new InviteRecord();
			recordDb.setId(record.getId());
			recordDb.setTip(0);
			inviteRecordMapper.updateById(recordDb);
		}
		result.setNewUserPrizeTip(newUserPrizeTip);*/
		result.setPrizeList(prizeList);
		return result;
	}
	@Override
	public List<UserVo> inviteList(InviteDto inviteDto) {
		String userId = inviteDto.getUserId();
		Integer id = inviteDto.getId();
		List<UserVo> list = inviteMapper.selectInviteList(INVITE_ID, id, userId);
		for (UserVo userVo : list) {
			if(StringUtils.isBlank(userVo.getAvatarUrl())){
				userVo.setAvatarUrl(Constants.DEFAULT_AVATAR);
			}
			userVo.setCreateTimeStr(DateUtil.localDateTimeToString(userVo.getCreateTime()));
			userVo.setCreateTime(null);
		}
		return list;
	}

	@Override
	public Map<String, Object> inviteSum(InviteDto inviteDto) {
		String userId = inviteDto.getUserId();
		//总邀请数
		LambdaQueryWrapper<InviteRecord> wrapper =  new LambdaQueryWrapper<>();
		wrapper.eq(InviteRecord::getInviteId, INVITE_ID).eq(InviteRecord::getTargetId, userId);
		Integer sumCount = inviteRecordMapper.selectCount(wrapper);
		//今日邀请数
		LambdaQueryWrapper<InviteRecord> queryWrapper =  new LambdaQueryWrapper<>();
		queryWrapper.eq(InviteRecord::getInviteId, INVITE_ID).eq(InviteRecord::getTargetId, userId).ge(InviteRecord::getCreateTime, DateUtil.getCurrentDateFirstSecond()).le(InviteRecord::getCreateTime, DateUtil.getCurrentDateLastSecond());
		Integer dayCount = inviteRecordMapper.selectCount(queryWrapper);
		//好友充值累计获得友情币数
		Integer sum = inviteCoinLogMapper.selectSum(INVITE_ID, userId);
		//返回
		Map<String, Object> result = new HashMap<>();
		result.put("sumCount", sumCount);
		result.put("dayCount", dayCount);
		result.put("rechargeCoin", sum == null ? 0 : sum);
		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Map<String, Object> exPrize(InviteDto inviteDto) {
		Invite invite = getInvite(INVITE_ID);
		String userId = inviteDto.getUserId();
		Integer id = inviteDto.getId();
		LocalDateTime now = LocalDateTime.now();
		if (id == null) {
			throw new ServiceException("id不能为空");
		}
		String key = RedisConstans.putRediskey(RedisConstans.INVITE_PRIZE_EXCHANGE, LocalDate.now().toString(), id.toString());
		//活动结束，不可兑换
		if(invite.getEndTime().isBefore(now)){
			throw new ServiceException("活动已结束~");
		}
		//屏蔽指定用户
		if(StringUtils.isNotBlank(invite.getProperty1())){
			JSONObject jsonObject = JSON.parseObject(invite.getProperty1());
			String accountId = jsonObject.getString(userId);
			if(StringUtils.isNotBlank(accountId)){
				throw new ServiceException("今日兑换奖励已达上限哦~");
			}
		}
		//查奖品
		InvitePrize prize = invitePrizeMapper.selectById(id);
		if(prize == null){
			throw new ServiceException("奖品不存在");
		}
		Integer currentCount = redisUtil.get(key);
		if(currentCount != null && currentCount >= prize.getDayNum()){
			throw new ServiceException(-3, "今日奖励已兑完，明天继续开放库存，继续加油哦");
		}
		//皮肤只能兑换3次
		if(prize.getSource().equals(InvitePrizeSourceEnum.SKIN.getValue())){
			LambdaQueryWrapper<InviteExchange> exWrapper = new LambdaQueryWrapper<>();
			exWrapper.eq(InviteExchange::getInviteId, INVITE_ID).eq(InviteExchange::getUserId, userId).eq(InviteExchange::getSource, InvitePrizeSourceEnum.SKIN.getValue());
			Integer count = inviteExchangeMapper.selectCount(exWrapper);
			if(count >= 3){
				throw new ServiceException(-2, "您兑换游戏皮肤奖品已达上限，请选择其他礼品吧");
			}
		}
		//发放奖品
		Integer coin = givePrize(userId, prize);
		//保存到
		redisUtil.incr(key);
		redisUtil.expire(key, DateUtil.getDayRemainingTime());
		//返回
		Map<String, Object> result = new HashMap<>();
		result.put("coin", coin);
		return result;
	}

	//插入访问记录
	@Override
	public boolean insertVisitRecord(String code, String ip){
		if(StringUtils.isBlank(code)){
			return false;
		}
		LambdaQueryWrapper<InviteLinkRecord> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(InviteLinkRecord::getInviteCode, code).eq(InviteLinkRecord::getIp, ip).last("limit 1");
		InviteLinkRecord record = inviteLinkRecordMapper.selectOne(queryWrapper);
		if (record != null) {
			record.setUpdateTime(LocalDateTime.now());
			int updateCount = inviteLinkRecordMapper.updateById(record);
			log.info("methodName:insertRecord, code={},ip={},更新记录={}", code, ip, updateCount);
			return true;
		}
		//查询邀请表中的奶爸
		LambdaQueryWrapper<InviteWallet> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(InviteWallet::getInvitteCode, code).last("limit 1");
		InviteWallet wallet = inviteWalletMapper.selectOne(wrapper);
		if (wallet == null) {
			log.error("methodName:insertRecord, code={},ip={},邀请码查询不到邀请人", code, ip);
			return false;
		}
		//插入到记录表
		InviteLinkRecord linkRecord = new InviteLinkRecord();
		linkRecord.setInviteId(INVITE_ID);
		linkRecord.setUserId(wallet.getUserId());
		linkRecord.setInviteCode(code);
		linkRecord.setIp(ip);
		linkRecord.setUpdateTime(LocalDateTime.now());
		inviteLinkRecordMapper.insert(linkRecord);
		return true;
	}

	@Override
	public List<PrizeVo> exRecordList(InviteDto inviteDto) {
		String userId = inviteDto.getUserId();
		Integer id = inviteDto.getId();
		List<PrizeVo> list = inviteExchangeMapper.selectList(INVITE_ID, id, userId);
		return list;
	}

	@Override
	public List<PrizeVo> lastExRecordList(InviteDto inviteDto) {
		return inviteExchangeMapper.selectLastList(INVITE_ID);
	}


	//发放奖品
	private Integer givePrize(String userId, InvitePrize prize) {
		Integer result = 0;
		//查钱包
		LambdaQueryWrapper<InviteWallet> walletWrapper = new LambdaQueryWrapper();
		walletWrapper.eq(InviteWallet::getInviteId, INVITE_ID).eq(InviteWallet::getUserId, userId).last("limit 1");
		InviteWallet inviteWallet = inviteWalletMapper.selectOne(walletWrapper);
		//钱包表是否有数据，没有则生成
		if(inviteWallet == null){
			//log.error("methodName:doMqDataByHandler, 邀请钱包数据不存在={}, userId={}", num, userId);
			String inviteCode = getInviteCode();
			InviteWallet record = new InviteWallet();
			record.setInviteId(INVITE_ID);
			record.setUserId(userId);
			record.setAmount(0);
			record.setInvitteCode(inviteCode);
			inviteWalletMapper.insert(record);
			//
			inviteWallet = new InviteWallet();
			BeanUtils.copyProperties(record, inviteWallet);
		}
		if(prize.getType().equals(InvitePrizeEnum.EX_PRIZE.getType())){//如果是兑换则需要扣减友情币
			if(inviteWallet.getAmount() < prize.getExNum()){
				throw new ServiceException("友情币不足");
			}
			//扣减友情币
			int row = inviteMapper.reduceAmount(inviteWallet.getId(), prize.getExNum());
			if(row < 1){
				throw new ServiceException("兑换失败，请稍后重试");
			}
			result = inviteWallet.getAmount() - prize.getExNum();
			redisUtil.del(RedisConstans.INVITE_WALLET + INVITE_ID + userId);
		}
		//插入记录
		InviteExchange exchange = new InviteExchange();
		exchange.setInviteId(INVITE_ID);
		exchange.setUserId(userId);
		exchange.setPrizeId(prize.getId());
		exchange.setPrizeName(prize.getName());
		exchange.setGiftId(prize.getGiftId());
		exchange.setNum(1);
		exchange.setSource(prize.getSource());
		exchange.setType(prize.getType());
		exchange.setValue(prize.getTotalValue());
		exchange.setExNum(prize.getExNum());
		exchange.setBeforeBalance(inviteWallet.getAmount());
		if(prize.getType().equals(InvitePrizeEnum.EX_PRIZE.getType())){
			exchange.setAfterBalance(inviteWallet.getAmount() - prize.getExNum());
		} else {
			exchange.setAfterBalance(inviteWallet.getAmount());
		}
		if(prize.getSource().equals(InvitePrizeSourceEnum.SKIN.getValue())){
			exchange.setStatus(0);
		}
		inviteExchangeMapper.insert(exchange);
		//String key = RedisConstans.putRediskey(RedisConstans.INVITE_PRIZE_RECORD, INVITE_ID, prize.getType(), userId);
		//来源，0=礼物，1=装扮，2=气泡框|尾件|挂件，3=钻石，4=王者皮肤
		Integer source = prize.getSource();
		if(source == 0 || source == 1){
			giftService.savePrize(-1, userId, prize.getGiftId(), prize.getType(), prize.getNum());
		} else if(source == 2) {
			giftService.saveUserDress(-1, userId, prize.getGiftId(), prize.getType(), prize.getNum(), "邀请好友获得");
		} else if(source == 3) {//钻石
			UserWallet wallet = userWalletMapper.selectByUserId(userId);
			if (wallet == null) {
				throw new ServiceException("钱包数据不存在");
			}
			int rows = userWalletMapper.addDiamondsAmount(wallet.getId(), prize.getTotalValue());
			if(rows < 1){
				throw new ServiceException("增加钻石失败");
			}
			//插入账本表
			UserAccountBook accountBook = new UserAccountBook();
			accountBook.setCurrencyType(9);
			accountBook.setOrderId(exchange.getId().toString());
			accountBook.setAccountTitle("友情币兑换");
			accountBook.setReceivingAccount(userId);
			accountBook.setReceivingAmount(prize.getTotalValue());
			accountBook.setReceivingAccountTotal(wallet.getDiamondsAmount());
			accountBook.setReceivingAccountBalance(wallet.getDiamondsAmount() + prize.getTotalValue());
			userAccountBookMapper.insert(accountBook);
		} else if(source == 4) {//友情币
			//增加友情币
			addCoin(inviteWallet.getId(), "0", userId, prize.getTotalValue(), 2, 0);
			result = inviteWallet.getAmount() + prize.getTotalValue();
		}
		return result;
	}

	//获取钱包表数据
	private InviteWallet getWallet(String userId){
		String key = RedisConstans.INVITE_WALLET + INVITE_ID + userId;
		InviteWallet wallet = redisUtil.get(key);
		if (wallet != null) {
			return wallet;
		}
		LambdaQueryWrapper<InviteWallet> wrapper = new LambdaQueryWrapper();
		wrapper.eq(InviteWallet::getInviteId, INVITE_ID).eq(InviteWallet::getUserId, userId).last("limit 1");
		wallet = inviteWalletMapper.selectOne(wrapper);
		redisUtil.set(key, wallet,RedisConstans.ONE_HOUR);
		return wallet;
	}

	//邀请信息
	private Invite getInvite(Integer id) {
		if(id == null){
			throw new ServiceException("id不能为空");
		}
		Invite invite = redisUtil.get(RedisConstans.INVITE + id);
		if(invite != null){
			return invite;
		}
		invite = getById(id);
		if(invite == null){
			throw new ServiceException("数据不存在");
		}
		redisUtil.set(RedisConstans.INVITE + id, invite, RedisConstans.ONE_DAY);
		return invite;
	}

	//增加友情币
	private void addCoin(Integer id, String userId, String targetId, Integer num, Integer type, Integer computeDiamond){
		//插入友情币记录
		InviteCoinLog coinLog = new InviteCoinLog();
		coinLog.setInviteId(INVITE_ID);
		coinLog.setUserId(userId);
		coinLog.setTargetId(targetId);
		coinLog.setNum(num);
		coinLog.setType(type);
		coinLog.setComputeDiamond(computeDiamond);
		inviteCoinLogMapper.insert(coinLog);
		//增加友情币
		if(id == null){
			InviteWallet wallet = getWallet(targetId);
			id = wallet.getId();
		}
		inviteWalletMapper.addAmount(id, num);
		log.warn("methodName:addCoin, id={},userId={},targetId={},num={},type={},computeDiamond={}", id , userId, targetId, num, type, computeDiamond);
		redisUtil.del(RedisConstans.INVITE_WALLET + INVITE_ID + targetId);
	}

	//给新用户发放新人奖励
	private void newcomerReward(String userId) {
		List<InvitePrize> prizeList = getInvitePrizeList(InvitePrizeEnum.INVITE_NEW_AWARD.getType());
		if(CollectionUtils.isEmpty(prizeList)){
			log.error("methodName:newcomerReward, 奖品不存在");
			return;
		}
		for (InvitePrize prize : prizeList) {
			//查收是否已发放
			LambdaQueryWrapper<InviteExchange> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.eq(InviteExchange::getInviteId, INVITE_ID).eq(InviteExchange::getInviteId, userId).eq(InviteExchange::getType, prize.getType()).eq(InviteExchange::getSource, prize.getSource()).eq(InviteExchange::getGiftId, prize.getGiftId());
			InviteExchange record = inviteExchangeMapper.selectOne(queryWrapper);
			if(record != null) {
				log.error("methodName:newcomerReward, 已发放新人奖励, userId={}", userId);
				return;
			}
			//发放奖励
			givePrize(userId, prize);
		}
	}

	/**
	 * 生成邀请码
	 *
	 * @return
	 */
	private String getInviteCode() {
		String inviteCode = CommonUtil.genRandomCode(6, 4);
		// 检查该邀请码是否存在
		LambdaQueryWrapper<InviteWallet> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(InviteWallet::getInvitteCode, inviteCode);
		Integer count = inviteWalletMapper.selectCount(queryWrapper);
		if (CommonUtil.checkSame(inviteCode) || count > 0){// 同号或连号或已存在该邀请码，重新获取一次
			return getInviteCode();
		}
		return inviteCode;
	}

	//根据概率获取友情币
	private Integer lottery() {
		// 获取所有抽奖奖品
		List<InviteRate> list = (List<InviteRate>) redisUtil.hget(RedisConstans.INVITE_RATE, INVITE_ID.toString());
		if(CollectionUtils.isEmpty(list)){
			list = inviteRateMapper.selectList(new LambdaQueryWrapper<InviteRate>().eq(InviteRate::getInviteId, INVITE_ID));
			if(CollectionUtils.isEmpty(list)){
				throw new ServiceException("概率数据不存在");
			}
		}
		redisUtil.hset(RedisConstans.INVITE_RATE, INVITE_ID.toString(), list,RedisConstans.ONE_HOUR);
		List<NewLotteryVo> lotteryList = new ArrayList<>();
		for (InviteRate rate : list) {
			NewLotteryVo vo = new NewLotteryVo();
			vo.setProbability((int)(rate.getRate() * 1000));
			vo.setNum(rate.getCoin());
			lotteryList.add(vo);
		}
		NewLotteryVo lotteryVo = CommonUtil.lotteryHigh(lotteryList);
		return lotteryVo.getNum();
	}

}
